/* Universidad del Valle de Guatemala
 * CC2003 - Algoritmos y Estructuras de Datos
 * PROYECTO #3: PI-LISP
 * Fecha de Entrega: Lunes 21 de Noviembre de 2011
 */

/**
 * Clase que representa las listas del intérprete Pi-Lisp.
 * @authors José Antonio Bagur - 10275, Emilio José Miranda - 10411, Luis Antonio Siguenza - 10297
 */

/* SE IMPORTAN LOS PAQUETES UTILIZADOS EN LA CLASE */
import java.util.*;

public class Lista extends ArrayList implements List {
    
        /* VARIABLES DE INSTANCIA */
    
        protected boolean isOp;
        
        /**
         * Constructor de la clase Lista, permite llamar al constructor de la estructura
         * ArrayList del JCF.
         */
        public Lista() {
            super();
        }
        
        /** 
         * Constructor de la clase Lista basado en un elemento Lista, permite llamar al 
         * constructor de la estructura ArrayList del JCF.
         * @param L lista a inicializar
         */
        public Lista(List L) {
            super();
            
            if(L == null) {
                L = new Lista();
            }
            
            for(int i = 0; i < L.size(); i++) {
                this.add(L.get(i));
            }
        }
        
        /**
         * Constructor de la clase Lista basado en un átomo, permite llamar al constructor
         * de la estructura ArrayList del JCF.
         * @param A 
         */
        public Lista(Atom A) {
            super();
            this.add(A);
        }
        
        /**
         * Método que permite conocer si la lista se encuentra vacía o no.
         * @return True si la lista se encuentra vacía
         */
        public boolean listIsEmpty() {
            if(this.size() == 0) {
                return true;
            } else {
                return false;
            }
        }
        
        /**
         * Método que permite agregar un elemento al final de la lista.
         * @param A 
         */
        public void addEnd(Atom A) {
            this.add(A);
        }
        
        /**
         * Método que permite agregar un elemento de tipo átomo en una posición
         * específica de la lista.
         * @param index posición del arreglo
         * @param A átomo a ingresar en la lista
         */
        public void addTo(int index, Atom A) {
            this.add(index, A);
        }
        
        /**
         * Método que permite conocer si existe un átomo determinado dentro de la
         * lista.
         * @param A átomo a buscar
         * @return True si existe el átomo dentro de la lista
         */
        public boolean thisExists(Atom A) {
            
            for(int i = 0; i < this.size(); i++) {
                if(this.get(i).equals(A)) {
                    return true;
                }
            }
            
            return false;
        }
        
        /**
         * Método que permite obtener un átomo de una posición específica de la Lista.
         * @param index posición del átomo
         * @return átomo determinado de la lista
         */
        public Atom getAtomIn(int index) {
            return (Atom) this.get(index);
        }
        
        /**
         * Método que permite obtener y remover un átomo de una posición específica
         * de la Lista.
         * @param index posición del átomo a remover
         * @return átomo determinado de la lista
         */
        public Atom removeAtomIn(int index) {
            Atom dummy = (Atom) this.remove(index);
            return dummy;
        }
        
        /**
         * Método que permite remplazar un átomo de una posición específica de la Lista.
         * @param index posición del átomo a remplazar
         * @param A átomo de remplazo
         * @return átomo remplazado
         */
        public Atom replaceFor(int index, Atom A) {
            Atom dummyAtom = this.removeAtomIn(index);
            this.addTo(index, A);
            return dummyAtom;
        }
                    
        /**
         * Método que permite conocer si existe una operación dentro de la Lista.
         * @return Null si no existe la operación
         */
        public Atom getOp() {
            if(!this.isOp) {
                System.out.println("---> ADVERTENCIA: NO EXISTE NINGUNA OPERACIÓN");
                return null;
            }
            
            return (Atom)this.get(0);
        }

}   // FIN DE LA CLASE LIST
